/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.gui.client;

import nfse.gui.client.data.*;
import nfse.gui.record.*;
import nfse.gui.client.reports.*;

import com.gwtext.client.widgets.grid.GridPanel;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.data.*;
import com.gwtext.client.widgets.*;
import com.gwtext.client.widgets.event.*;
import com.gwtext.client.widgets.menu.*;
import com.gwtext.client.widgets.ToolTip;
import com.gwtext.client.widgets.form.Field;
import com.gwtext.client.widgets.form.NumberField;
import com.gwtext.client.widgets.form.TextField;
import com.gwtext.client.widgets.form.event.FieldListenerAdapter;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.event.*;
import com.gwtext.client.widgets.grid.*;
import com.gwtext.client.util.Format;
import com.gwtext.client.core.*;
import java.util.*;

public class BaseGridPanel extends Panel {
    NetFSEClient client = null;

    FlexRecordGroup flexRecordGroup;

    AnalysisPanel analysisPanel;

    TopValues topValues;

    GridPanel grid;

    Object[][] records;

    TextField currentPageTxt;

    NumberField pagingSizeTxt;

    private HashMap dataMap;

    public int lastColumnSorted = -1;

    public String lastColumnSortedDirection = "asc";

    private ArrayList fieldDefList = new ArrayList();

    private ArrayList columnConfigList = new ArrayList();

    ToolbarButton firstPageBtn = new ToolbarButton();

    ToolbarButton prevPageBtn = new ToolbarButton();

    ToolbarButton nextPageBtn = new ToolbarButton();

    ToolbarButton lastPageBtn = new ToolbarButton();

    ToolbarTextItem recordInfo = new ToolbarTextItem("");

    ToolbarTextItem pageCountTextItem = new ToolbarTextItem("");

    // Paging fields
    int currentFirstRecord = 0;

    int pageSize = 0;

    int pageCount = 0;

    int currentPage = 1;

    int totalResultRecords = 0;

    int lastRecordOnPage = 0;

    String displayType = "";

    int panelWidth = 920;

    boolean topValuesGrid = false;

    int[] columnWidths;

    public BaseGridPanel(NetFSEClient client, AnalysisPanel analysisPanel, TopValues topValues, int summaryType) {
        this.analysisPanel = analysisPanel;
        this.topValues = topValues;
        records = getRecords(topValues);
        displayType = "Summary";
        if (summaryType == NetFSEClient.FIELD_DST_IP)
            displayType = "Summary Top Destination IPs";
        else if (summaryType == NetFSEClient.FIELD_SRC_IP)
            displayType = "Summary Top Source IPs";
        else if (summaryType == NetFSEClient.FIELD_DST_PORT)
            displayType = "Summary Top Destination Ports";
        else if (summaryType == NetFSEClient.FIELD_PROTOCOL)
            displayType = "Summary Top Protocols";
        topValuesGrid = true;
        pageSize = 10;
    }

    public BaseGridPanel(NetFSEClient client, AnalysisPanel analysisPanel, FlexRecordGroup flexRecordGroup,
            int totalResultRecords) {
        this.analysisPanel = analysisPanel;
        this.flexRecordGroup = flexRecordGroup;
        this.totalResultRecords = totalResultRecords;
        records = getRecords(flexRecordGroup);
        displayType = "Results";
    }

    public void buildGrid(String title, int[] columnWidths) {
        // testData();
        this.columnWidths = columnWidths;

        buildColumns();
        // getCompanyData();

        Panel panel = new Panel();
        panel.setBorder(false);
        this.setTitle(title + " " + displayType);
        // this.setWidth(panelWidth);

        MemoryProxy proxy = new MemoryProxy(getDataPage(currentFirstRecord));

        if (topValuesGrid)
            proxy = new MemoryProxy(records);

        Iterator it = fieldDefList.iterator();
        FieldDef[] fieldDef = new FieldDef[fieldDefList.size()];
        int y = 0;
        while (it.hasNext()) {
            fieldDef[y++] = (FieldDef) it.next();
        }

        ArrayReader reader = new ArrayReader(new RecordDef(fieldDef));
        final Store store = new Store(proxy, reader, true);

        it = columnConfigList.iterator();
        ColumnConfig[] columns = new ColumnConfig[columnConfigList.size()];
        y = 0;
        while (it.hasNext()) {
            columns[y++] = (ColumnConfig) it.next();
        }
        ColumnModel columnModel = new ColumnModel(columns);

        store.load();

        grid = new GridPanel();
        grid.setAutoScroll(true);
        grid.setStore(store);
        grid.setColumnModel(columnModel);
        grid.setFrame(true);
        grid.setStripeRows(true);
        grid.setEnableHdMenu(false);
        // grid.setWidth(panelWidth);
        // grid.setHeight(300);

        grid.addGridHeaderListener(new GridHeaderListenerAdapter() {
            public void onHeaderContextMenu(GridPanel grid, int colIndex, EventObject e) {
                System.out.println(Format.format("GridHeaderListener.onHeaderContextMenu:: colIndex({0}))", colIndex));
            }

            public void onHeaderClick(GridPanel grid, int colIndex, EventObject e) {
                int currentSelectedCol = colIndex;
                //System.out.println(Format.format("GridHeaderListener.onHeaderClick:: colIndex({0}))", colIndex));
                if (lastColumnSorted == currentSelectedCol) {
                    lastColumnSortedDirection = "desc";
                } else {
                    lastColumnSortedDirection = "asc";
                }

                lastColumnSorted = colIndex;
                analysisPanel.sortResultsColumn(flexRecordGroup, colIndex, lastColumnSortedDirection);
                // Reset the page status to the first page and reset the info
                // toolbar for what page you are on
                currentFirstRecord = 0;
                currentPageTxt.setValue("1");
                currentPage = 1;
                lastRecordOnPage = currentFirstRecord + pageSize;
            }

        });

        Toolbar pagingToolbar = new Toolbar();
        currentPageTxt = new TextField();
        currentPageTxt.setValue("1");
        recordInfo.setText("Displaying records " + (currentFirstRecord + 1) + " - " + (currentFirstRecord + pageSize)
                + " of " + totalResultRecords);

        firstPageBtn.setIconCls("x-tbar-page-first");
        pagingToolbar.addButton(firstPageBtn);
        ToolTip firstPageTP = new ToolTip("First Page");
        firstPageTP.applyTo(firstPageBtn);
        firstPageBtn.addListener(new ButtonListenerAdapter() {
            public void onClick(Button button, EventObject e) {
                currentFirstRecord = 0;
                getNewPage(-5);
                currentPageTxt.setValue("1");
                currentPage = 1;

                disablePageToolBarControls();
                lastRecordOnPage = currentFirstRecord + pageSize;
                if (totalResultRecords < pageSize)
                    lastRecordOnPage = currentFirstRecord + totalResultRecords;
            }
        });

        prevPageBtn.setIconCls("x-tbar-page-prev");
        pagingToolbar.addButton(prevPageBtn);
        ToolTip prevPageTP = new ToolTip("Previous Page");
        prevPageTP.applyTo(prevPageBtn);
        prevPageBtn.addListener(new ButtonListenerAdapter() {
            public void onClick(Button button, EventObject e) {
                currentFirstRecord = currentFirstRecord - pageSize;
                if (currentFirstRecord < 0)
                    currentFirstRecord = 0;

                // Handle case where this is the first page. The -5 allows using
                // the same code to retrieve a page and add it to an existing
                // grid rather than creating a new grid.
                // The -5 is handled in the getResultTypes Success method
                if (currentFirstRecord == 0)
                    getNewPage(-5);
                else
                    getNewPage(currentFirstRecord);
                currentPage--;

                disablePageToolBarControls();
                lastRecordOnPage = currentFirstRecord + pageSize;
            }
        });

        pagingToolbar.addItem(new ToolbarSeparator());
        pagingToolbar.addItem(new ToolbarTextItem("Page: "));

        currentPageTxt.setWidth(40);
        pagingToolbar.addField(currentPageTxt);

        pageCountTextItem.setText("of  " + pageCount);
        pagingToolbar.addItem(pageCountTextItem);

        pagingToolbar.addItem(new ToolbarSeparator());

        nextPageBtn.setIconCls("x-tbar-page-next");
        pagingToolbar.addButton(nextPageBtn);
        ToolTip nextPageTP = new ToolTip("Next Page");
        nextPageTP.applyTo(nextPageBtn);
        nextPageBtn.addListener(new ButtonListenerAdapter() {
            public void onClick(Button button, EventObject e) {

                currentFirstRecord = currentFirstRecord + pageSize;
                if (currentFirstRecord > totalResultRecords)
                    currentFirstRecord = totalResultRecords - pageSize;
                getNewPage(currentFirstRecord);
                currentPage++;
                currentPageTxt.setValue(currentPage + "");
                int tempTotal = currentFirstRecord + pageSize;
                if (tempTotal > totalResultRecords)
                    tempTotal = totalResultRecords;

                disablePageToolBarControls();
                lastRecordOnPage = tempTotal;
            }
        });

        lastPageBtn.setIconCls("x-tbar-page-last");
        pagingToolbar.addButton(lastPageBtn);
        ToolTip lastPageTP = new ToolTip("Last Page");
        lastPageTP.applyTo(lastPageBtn);
        lastPageBtn.addListener(new ButtonListenerAdapter() {
            public void onClick(Button button, EventObject e) {
                currentFirstRecord = totalResultRecords - (pageSize - ((pageSize * pageCount) % totalResultRecords));
                getNewPage(currentFirstRecord);
                currentPageTxt.setValue(pageCount + "");
                currentPage = pageCount;
                int tempTotal = currentFirstRecord + pageSize;
                if (tempTotal > totalResultRecords)
                    tempTotal = totalResultRecords;

                disablePageToolBarControls();
                lastRecordOnPage = tempTotal;
            }
        });

        pagingToolbar.addItem(new ToolbarSeparator());

        pagingSizeTxt = new NumberField();
        pagingSizeTxt.setWidth(20);
        pagingSizeTxt.setMaxValue(totalResultRecords);
        pagingSizeTxt.setMaxText("Exceeds the total number of records ");

        ToolTip refreshPageTP = new ToolTip("Set New Page Size");
        refreshPageTP.applyTo(pagingSizeTxt);

        pagingToolbar.addField(pagingSizeTxt);

        ToolbarButton refreshPageBtn = new ToolbarButton();
        refreshPageBtn.setIcon("./js/ext/resources/images/default/grid/refresh.gif");
        pagingToolbar.addButton(refreshPageBtn);
        ToolTip refreshTP = new ToolTip("Refresh Page");
        refreshTP.applyTo(refreshPageBtn);
        refreshPageBtn.addListener(new ButtonListenerAdapter() {
            public void onClick(Button button, EventObject e) {
                String tempTxt = pagingSizeTxt.getText();
                if (tempTxt != null) {
                    pageSize = new Integer(tempTxt).intValue();
                    currentPageTxt.setValue("1");
                    currentPage = 1;
                    currentFirstRecord = 0;
                    pageCount = totalResultRecords / pageSize;
                    int excessPage = totalResultRecords % pageSize;
                    if (excessPage != 0)
                        pageCount += 1;

                    pageCountTextItem.setText("of  " + pageCount);
                    int tempCount = pageSize;
                    if (pageSize > totalResultRecords)
                        tempCount = totalResultRecords;

                    int tempFirstRecord = 1;
                    if (totalResultRecords == 0)
                        tempFirstRecord = 0;

                    recordInfo.setText("Displaying records " + tempFirstRecord + " - " + tempCount + " of "
                            + totalResultRecords);
                    if (totalResultRecords > pageSize) {
                        firstPageBtn.disable();
                        prevPageBtn.disable();
                        lastPageBtn.enable();
                        nextPageBtn.enable();
                    }
                    getNewPage(currentFirstRecord);
                }
            }
        });

        pagingToolbar.addFill();

        resetPagingToolbarStatusAfterNewQuery();
        setPagingToolBarStatus();
        pagingToolbar.addItem(recordInfo);
        if (!topValuesGrid)
            grid.setBottomToolbar(pagingToolbar);

        panel.add(grid);

        this.add(panel);
    }

    public void getNewPage(int startRecord) {
        analysisPanel.getTypeResults(flexRecordGroup.typeID, startRecord);
    }

    public void addPageToTab() {
        MemoryProxy proxy = new MemoryProxy(records);

        Iterator it = fieldDefList.iterator();
        FieldDef[] fieldDef = new FieldDef[fieldDefList.size()];
        int y = 0;
        while (it.hasNext()) {
            fieldDef[y++] = (FieldDef) it.next();
        }
        RecordDef recordDef = new RecordDef(fieldDef);

        ArrayReader reader = new ArrayReader(recordDef);
        final Store store = new Store(proxy, reader, true);

        it = columnConfigList.iterator();
        ColumnConfig[] columns = new ColumnConfig[columnConfigList.size()];
        y = 0;
        while (it.hasNext()) {
            columns[y++] = (ColumnConfig) it.next();
        }

        ColumnModel columnModel = new ColumnModel(columns);

        store.load();
        grid.reconfigure(store, columnModel);

    }

    public void disablePageToolBarControls() {
        firstPageBtn.disable();
        prevPageBtn.disable();
        lastPageBtn.disable();
        nextPageBtn.disable();
    }

    public void resetPagingToolbarStatusAfterNewQuery() {
        currentFirstRecord = 0;
        currentPage = 1;
        pageCount = totalResultRecords / pageSize;
        int excessPage = totalResultRecords % pageSize;
        // Add one more page if the record count is not divided evenly by the
        // page size
        if (excessPage != 0)
            pageCount += 1;
    }

    public void setPagingToolBarStatus() {
        if (totalResultRecords < pageSize)
            this.lastRecordOnPage = totalResultRecords;

        lastRecordOnPage = currentFirstRecord + pageSize;
        if (totalResultRecords < pageSize) {
            lastRecordOnPage = currentFirstRecord + totalResultRecords;
            pageCount = 1;
        }

        if (lastRecordOnPage > totalResultRecords)
            lastRecordOnPage = totalResultRecords;
        currentPageTxt.setValue(currentPage + "");
        pageCountTextItem.setText("of  " + pageCount);

        recordInfo.setText("Displaying records " + (currentFirstRecord + 1) + " - " + lastRecordOnPage + " of "
                + totalResultRecords);
        // Disable all of them then depending on conditions selectively enable
        // them
        disablePageToolBarControls();

        // First Record and more than one page of records
        if ((currentFirstRecord == 0) && (totalResultRecords > pageSize + 1)) {
            lastPageBtn.enable();
            nextPageBtn.enable();
        }

        // Somewhere in the middle
        if ((currentFirstRecord > 0) && (currentPage < pageCount)) {
            firstPageBtn.enable();
            prevPageBtn.enable();
            lastPageBtn.enable();
            nextPageBtn.enable();
        }

        // On the last page
        if ((currentFirstRecord > 0) && (currentPage == pageCount)) {
            firstPageBtn.enable();
            prevPageBtn.enable();
        }
    }

    private Object[][] getDataPage(int startIdx) {
        int targetIdx = 0;
        int lastRecord = totalResultRecords;
        if (startIdx + pageSize < totalResultRecords)
            lastRecord = startIdx + pageSize;
        int actualPageSize = pageSize;
        if (lastRecord != totalResultRecords)
            actualPageSize = lastRecord - startIdx + 1;
        Object[][] targetRecords = new Object[actualPageSize][9];
        for (int i = startIdx; i < lastRecord; i++) {
            targetRecords[targetIdx++] = records[i];
        }

        return targetRecords;

    }

    /**
     * This handles the Summary tables for a specific type. This should be
     * refactored out into its own class since the rest of this class does not
     * have domain specific namely hardcoded column types
     * 
     * @param topValues
     * @return
     */
    private Object[][] getRecords(TopValues topValues) {
        flexRecordGroup = new FlexRecordGroup();

        FlexRecordField[] frf = new FlexRecordField[6];

        frf[0] = new FlexRecordField();
        frf[0].type = FlexRecordField.TYPE_STRING;
        frf[0].name = "Value";
        frf[0].columnWidth = 100;
        frf[0].sortable = false;

        frf[1] = new FlexRecordField();
        frf[1].type = FlexRecordField.TYPE_STRING;
        frf[1].name = "Time View";
        frf[1].columnWidth = 200;
        frf[1].sortable = false;

        frf[2] = new FlexRecordField();
        frf[2].type = FlexRecordField.TYPE_INT;
        frf[2].name = "Low";
        frf[2].columnWidth = 50;
        frf[2].sortable = false;

        frf[3] = new FlexRecordField();
        frf[3].type = FlexRecordField.TYPE_INT;
        frf[3].name = "High";
        frf[3].columnWidth = 50;
        frf[3].sortable = false;

        frf[4] = new FlexRecordField();
        frf[4].type = FlexRecordField.TYPE_INT;
        frf[4].name = "Total";
        frf[4].columnWidth = 50;
        frf[4].sortable = false;

        frf[5] = new FlexRecordField();
        frf[5].type = FlexRecordField.TYPE_INT;
        frf[5].name = "% Activity";
        frf[5].columnWidth = 100;
        frf[5].sortable = false;

        flexRecordGroup.flexRecordFields = frf;

        records = new Object[topValues.values.length][6];

        for (int x = 0; x < topValues.values.length; x++) {
            records[x][0] = topValues.values[x];

            String html = "<img src=\"/nfse/spark?height=20&type=line&color=blue&data=";
            for (int j = 0; j < topValues.stats[x].length; j++) {
                if (j > 0)
                    html += ",";
                html += topValues.stats[x][j];
            }
            html += "\" />";

            records[x][1] = html;

            records[x][2] = topValues.lows[x];
            records[x][3] = topValues.highs[x];
            records[x][4] = topValues.totals[x];
            records[x][5] = topValues.percents[x];
        }
        return records;
    }

    public Object[][] getRecords(FlexRecordGroup frg) {
        // this.pageSize = frg.records.length;
        this.pageSize = analysisPanel.getN(0);

        records = new Object[frg.records.length][frg.getColumnNames().length];
        for (int x = 0; x < frg.records.length; x++) {
            records[x] = (Object[]) frg.records[x].values;
        }

        return records;

    }

    /**
     * This builds the record Defs for each column type and the column configs
     * for each column
     */
    private void buildColumns() {

        for (int x = 0; x < flexRecordGroup.getColumnNames().length; x++) {
            ColumnConfig cc = null;
            FlexRecordField frField = flexRecordGroup.flexRecordFields[x];
            // String tempFieldName = "";
            switch (flexRecordGroup.flexRecordFields[x].type) {
            case FlexRecordField.TYPE_INT:
                fieldDefList.add(new IntegerFieldDef(frField.name));
                cc = new ColumnConfig(frField.name, frField.name, frField.columnWidth, frField.sortable);
                cc.setAlign(TextAlign.RIGHT);
                cc.setWidth(columnWidths[x]);
                columnConfigList.add(cc);
                break;

            case FlexRecordField.TYPE_FLOAT:
                fieldDefList.add(new FloatFieldDef(frField.name));
                cc = new ColumnConfig(frField.name, frField.name, frField.columnWidth, frField.sortable);
                cc.setAlign(TextAlign.RIGHT);
                cc.setWidth(columnWidths[x]);
                columnConfigList.add(cc);
                break;

            case FlexRecordField.TYPE_STRING:
                fieldDefList.add(new StringFieldDef(frField.name));
                cc = new ColumnConfig(frField.name, frField.name, frField.columnWidth, frField.sortable);
                cc.setAlign(TextAlign.LEFT);
                cc.setWidth(columnWidths[x]);
                columnConfigList.add(cc);
                break;

            case FlexRecordField.TYPE_BOOLEAN:
                fieldDefList.add(new BooleanFieldDef(frField.name));
                cc = new ColumnConfig(frField.name, frField.name, frField.columnWidth, frField.sortable);
                cc.setAlign(TextAlign.LEFT);
                cc.setWidth(columnWidths[x]);
                columnConfigList.add(cc);
                break;

            case FlexRecordField.TYPE_LONG:
                fieldDefList.add(new IntegerFieldDef(frField.name));
                cc = new ColumnConfig(frField.name, frField.name, frField.columnWidth, frField.sortable);
                cc.setAlign(TextAlign.RIGHT);
                cc.setWidth(columnWidths[x]);
                columnConfigList.add(cc);
                break;

            case FlexRecordField.SUB_TYPE_IMAGE:
                fieldDefList.add(new StringFieldDef(frField.name));
                cc = new ColumnConfig(frField.name, frField.name, frField.columnWidth, frField.sortable,
                        new Renderer() {
                            public String render(Object value, CellMetadata cellMetadata, Record record, int rowIndex,
                                    int colNum, Store store) {
                                return "fill in with graph image";
                            }
                        }, frField.name);
                cc.setAlign(TextAlign.RIGHT);
                columnConfigList.add(cc);
                break;

            default:
                break;

            }
        }

    }

    private void getCompanyData() {

        records = new Object[][] {
                new Object[] { "3m Co", new Double(71.72), new Double(0.02), new Double(0.03), "9/1 12:00am", "MMM",
                        "Manufacturing" },
                new Object[] { "Alcoa Inc", new Double(29.01), new Double(0.42), new Double(1.47), "9/1 12:00am", "AA",
                        "Manufacturing" },
                new Object[] { "Altria Group Inc", new Double(83.81), new Double(0.28), new Double(0.34),
                        "9/1 12:00am", "MO", "Manufacturing" },
                new Object[] { "American Express Company", new Double(52.55), new Double(0.01), new Double(0.02),
                        "9/1 12:00am", "AXP", "Finance" },
                new Object[] { "American International Group, Inc.", new Double(64.13), new Double(0.31),
                        new Double(0.49), "9/1 12:00am", "AIG", "Services" },
                new Object[] { "AT&T Inc.", new Double(31.61), new Double(-0.48), new Double(-1.54), "9/1 12:00am",
                        "T", "Services" },
                new Object[] { "Boeing Co.", new Double(75.43), new Double(0.53), new Double(0.71), "9/1 12:00am",
                        "BA", "Manufacturing" },
                new Object[] { "Caterpillar Inc.", new Double(67.27), new Double(0.92), new Double(1.39),
                        "9/1 12:00am", "CAT", "Services" },
                new Object[] { "Citigroup, Inc.", new Double(49.37), new Double(0.02), new Double(0.04), "9/1 12:00am",
                        "C", "Finance" },
                new Object[] { "E.I. du Pont de Nemours and Company", new Double(40.48), new Double(0.51),
                        new Double(1.28), "9/1 12:00am", "DD", "Manufacturing" } };

    }

    private void testData() {
        flexRecordGroup = new FlexRecordGroup();
        FlexRecordField[] frfA = new FlexRecordField[7];
        flexRecordGroup.flexRecordFields = frfA;

        FlexRecordField frField1 = new FlexRecordField();
        frField1.type = FlexRecordField.TYPE_STRING;
        frField1.name = "Company";
        frField1.columnWidth = 100;
        frField1.sortable = true;
        frfA[0] = frField1;

        FlexRecordField frField2 = new FlexRecordField();
        frField2.type = FlexRecordField.TYPE_FLOAT;
        frField2.name = "Price";
        frField2.columnWidth = 50;
        frField2.sortable = true;
        frfA[1] = frField2;

        FlexRecordField frField3 = new FlexRecordField();
        frField3.type = FlexRecordField.TYPE_FLOAT;
        frField3.name = "Change";
        frField3.columnWidth = 100;
        frField3.sortable = true;
        frfA[2] = frField3;

        FlexRecordField frField4 = new FlexRecordField();
        frField4.type = FlexRecordField.TYPE_FLOAT;
        frField4.name = "Pct Change";
        frField4.columnWidth = 100;
        frField4.sortable = true;
        frfA[3] = frField4;

        FlexRecordField frField5 = new FlexRecordField();
        frField5.type = FlexRecordField.SUB_TYPE_DATE;
        frField5.name = "Last Changed";
        frField5.columnWidth = 100;
        frField5.sortable = false;
        frfA[4] = frField5;

        FlexRecordField frField6 = new FlexRecordField();
        frField6.type = FlexRecordField.TYPE_STRING;
        frField6.name = "Symbol";
        frField6.columnWidth = 50;
        frField6.sortable = true;
        frfA[5] = frField6;

        FlexRecordField frField7 = new FlexRecordField();
        frField7.type = FlexRecordField.TYPE_STRING;
        frField7.name = "Industry";
        frField7.columnWidth = 150;
        frField7.sortable = true;
        frfA[6] = frField7;

    }

    public static String getProtocolName(int proto) {
        String protoStr = "" + proto;
        if (proto == 6)
            protoStr = "TCP";
        else if (proto == 1)
            protoStr = "ICMP";
        else if (proto == 17)
            protoStr = "UDP";
        return protoStr;
    }

}
